package org.fas.air.base
{
	import flash.desktop.Updater;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLStream;
	import flash.utils.ByteArray;
	import flash.utils.clearTimeout;
	import flash.utils.setTimeout;
	
	public class FAutoUpdate extends EventDispatcher
	{
		public var needRestart:Boolean = false;
		static public const TOO_LOWEST:String = "TOO_LOWEST";
		static public const NET_ERROR:String = "NET_ERROR";
		static public const INSTALL_ERROR:String = "INSTALL_ERROR";
		static public const DOWNLOAD_IO_ERROR:String = "DOWNLOAD_IO_ERROR";
		static public const DOWNLOAD_SECURITY_ERROR:String = "DOWNLOAD_SECURITY_ERROR";
		static public const DONE:String = "DONE";
		static public const DOWNLOADING:String = "DOWNLOADING";
		static public const PROGRESSING:String = "PROGRESSING";
		static public const INSTALLING:String = "INSTALLING";
		public var serverVerAll:String = '';
		public var serverVersion:Number = 0;
		public var serverSubVer:Number = 0;
		private var serverLastModifyDateStr:String;
		public var localVersion:Number = 0;
		private var localSubVer:Number = 0;
		private var localLastModifyDateStr:String;
		public var nowDownNo:int = 0;
		private var downFiles:Array = new Array();
		private var url_update:String;
		private var urlUpdateFolder:String;
		private var urlStream:URLStream;
		private var callback:Function;
		private var urlLoader:URLLoader;
		public function FAutoUpdate()
		{
		}
		public function get fileSum():int{
			return this.downFiles.length;
		}
		private var timerId:int = -1;
		public function check(_callback:Function):void{
			this.callback = _callback;
			setTimer();
			//load local version
			urlLoader = new URLLoader();
			urlLoader.addEventListener(Event.COMPLETE,this.evtLocalVersionCb);
			addNetEvent();
			urlLoader.load(new URLRequest('AutoUpdateConfig.xml'));
		}
		private function evtNetTimeOut():void{
			this.evtNetError();
		}
		private function evtNetError(_e:IOErrorEvent=null):void{
			this.clearTimer();
			this.removeNetEvent();
			this.callback(NET_ERROR);
		}
		private function addNetEvent():void{
			urlLoader.addEventListener(IOErrorEvent.IO_ERROR,this.evtNetError);
		}
		private function removeNetEvent():void{
			urlLoader.removeEventListener(IOErrorEvent.IO_ERROR,evtNetError);
		}
		private function setTimer():void{
			timerId = flash.utils.setTimeout(evtNetTimeOut,16000);
		}
		private function clearTimer():void{
			flash.utils.clearTimeout(this.timerId);
		}
		private function evtLocalVersionCb(_e:Event):void{
			this.clearTimer();
			this.removeNetEvent();
			urlLoader.removeEventListener(Event.COMPLETE,this.evtLocalVersionCb);
			evtLocalVersion(_e.target.data);
		}
		private function evtLocalVersion(_result:Object):void{
			var _xml:XML = XML(_result.toString());
			this.urlUpdateFolder = _xml.url_update_folder;
			//check service version
			setTimer();
			this.urlLoader = new URLLoader();
			this.url_update = _xml.url_update;
			this.addNetEvent();
			urlLoader.addEventListener(Event.COMPLETE,this.evtServerVersionCb);
			urlLoader.load(new URLRequest(_xml.url_update));
		}
		private function evtServerVersionCb(_e:Event):void{
//			trace('s load C');
			this.clearTimer();
			this.removeNetEvent();
			urlLoader.removeEventListener(Event.COMPLETE,this.evtServerVersionCb);
			evtServerVersion(_e.target.data);
		}
		private function evtServerVersion(_result:Object):void{
			var _server:XML = XML(_result);
			this.serverVersion = _server.item[0].version;
			//
			var _lowest_ver:Number = _server.item[0].lowest_version;
			var _lowest_sub:Number = _server.item[0].lowest_sub_ver;
			//
			var files:XMLList = _server.item[0].file;
			for(var i:int = 0;i<files.length();i++){
				this.downFiles.push(files[i]);
			}
			//
//			trace(serverVersion,localVersion,'-',this.serverSubVer,this.localSubVer);
			if(localVersion<_lowest_ver || (localVersion==_lowest_ver && localSubVer<_lowest_sub)){
//				trace(localVersion,_lowest_ver,localSubVer,_lowest_sub);
//				trace((localVersion==_lowest_ver && localSubVer<_lowest_sub));
				this.callback(TOO_LOWEST);
				return;
			}
			if(serverVersion>localVersion || this.serverSubVer>this.localSubVer){
//				this.needRestart = true;
//				trace(this.needRestart);
				this.download();
			}else{
				this.callback(DONE);
			}
		}
		public function download():void{
			nowDownNo = 0;
			downFileSimple();
		}
		private function downFileSimple():void{
			this.callback(DOWNLOADING);
			var _reg:URLRequest = new URLRequest(this.urlUpdateFolder+this.downFiles[nowDownNo]);
			this.urlStream = new URLStream();
			this.newFile = new File(File.applicationDirectory.resolvePath('temp/'+this.downFiles[nowDownNo].toString().replace('.jpg','')).nativePath);
			this.newFileStream = new FileStream();
			newFileStream.open(newFile,FileMode.WRITE);
			urlStream.removeEventListener(Event.COMPLETE,downloadFileComplete);
			urlStream.removeEventListener(ProgressEvent.PROGRESS,downloadProgress);
			urlStream.removeEventListener(IOErrorEvent.IO_ERROR,downloadIoError);
			urlStream.removeEventListener(SecurityErrorEvent.SECURITY_ERROR,downloadSecurityError);
			urlStream.addEventListener(Event.COMPLETE,downloadFileComplete);
			urlStream.addEventListener(ProgressEvent.PROGRESS,downloadProgress);
			urlStream.addEventListener(IOErrorEvent.IO_ERROR,downloadIoError);
			urlStream.addEventListener(SecurityErrorEvent.SECURITY_ERROR,downloadSecurityError);
			urlStream.load(_reg);
		}
		public var proTotle:Number = 1;
		public var proLoad:Number = 0;
		private function downloadIoError(_e:IOErrorEvent):void{
			this.callback(FAutoUpdate.DOWNLOAD_IO_ERROR);
		}
		private function downloadSecurityError(_e:SecurityErrorEvent):void{
			this.callback(FAutoUpdate.DOWNLOAD_SECURITY_ERROR);
		}
		private function downloadProgress(_e:ProgressEvent):void{
			proLoad = _e.bytesLoaded;
			proTotle = _e.bytesTotal;
			this.callback(PROGRESSING);
			if(this.urlStream.bytesAvailable>51200){
				var data:ByteArray = new ByteArray();
				this.urlStream.readBytes(data,0,this.urlStream.bytesAvailable);
				this.newFileStream.writeBytes(data,0,data.length);
			}
		}
		private var newFile:File;
		private var newFileStream:FileStream;
		private function downloadFileComplete(_e:Event):void{
			var data:ByteArray=new ByteArray();
			urlStream.readBytes(data,0,this.urlStream.bytesAvailable);
//			fileStream.addEventListener(Event.COMPLETE,this.downComplete);
//			fileStream.openAsync(newFile,FileMode.WRITE);
			newFileStream.writeBytes(data,0,data.length);
			newFileStream.close();
			if(this.nowDownNo<this.downFiles.length-1){
				this.nowDownNo++;
				this.downFileSimple();
			}else{
				install();
			}
		}
		private function install():void{
			this.callback(INSTALLING);
			for(var i:int = 0;i<this.downFiles.length;i++){
				var oldFile:File = new File(File.applicationDirectory.resolvePath('temp/'+this.downFiles[i].toString().replace('.jpg','')).nativePath);
				var newFile:File = new File(File.applicationDirectory.resolvePath(this.downFiles[i].toString().replace('.jpg','')).nativePath);
				oldFile.copyTo(newFile,true);
			}
			updateLocalVersion();
		}
		/**
		 * modify config.xml
		 * 
		 */		
		private function updateLocalVersion():void{
//			for(var i:int = 0;i<this.downFiles.length;i++){
//				var oldFile:File = new File(File.applicationDirectory.resolvePath('temp/'+this.downFiles[nowDownNo]).nativePath);
//				//oldFile.deleteFile();
//			}
			var _file:File = new File(File.applicationDirectory.resolvePath("AutoUpdateConfig.xml").nativePath);
			var stream:FileStream = new FileStream();
			stream.open(_file,FileMode.READ);
			var _data:String = stream.readUTFBytes(stream.bytesAvailable);
			stream.close();
			stream.open(_file,FileMode.WRITE);
			//= stream.readUTFBytes(stream.bytesAvailable);
			var xml:XML = 	<data> 
								<version></version> 
								<sub_ver></sub_ver>
								<last_modify_date></last_modify_date>
								<url_update></url_update>
								<url_update_folder></url_update_folder>
							</data>
			xml.version = this.serverVersion;
			xml.last_modify_date = this.serverLastModifyDateStr;
			xml.sub_ver  = this.serverSubVer;
			xml.url_update = this.url_update;
			xml.url_update_folder = this.urlUpdateFolder;
			
			var _configStr:String = '<?xml version="1.0" encoding="UTF-8"?>\n'+xml.toString();
			stream.writeUTFBytes(_configStr);
			stream.close();
			var _updater:Updater = new Updater();
			this.callback(DONE);
		}
		/**
		 * get and set functions 
		 * @return 
		 * 
		 */		
		public function get sumUpdateFile():int{
			return this.downFiles.length;
		}
		
	}
}